/**
 * @file boxInfoEncode.h
 * @author SDK_TEAM
 * @brief
 * @version 0.1
 * @date 2022-11-02
 *
 * Copyright:
 * © 2018 北京灵汐科技有限公司 版权所有。
 * 注意：以下内容均为北京灵汐科技有限公司原创，未经本公司允许，不得转载，否则将视为侵权；对于不遵守此声明或者其他违法使用以下内容者，本公司依法保留追究权。
 * © 2018 Lynxi Technologies Co., Ltd. All rights reserved.
 * NOTICE: All information contained here is, and remains the property of Lynxi.
 * This file can not be copied or distributed without the permission of Lynxi
 * Technologies Co., Ltd.
 *
 */

#pragma once

#include <lyn_api.h>
#include <codecvt>
#include <fstream>
#include <iomanip>
#include <locale>
#include <string>
#include "boxInfo.h"
#include "framePool.hpp"
#include "nlohmann/json.hpp"

using json = nlohmann::json;

class BoxInfoEncode;

typedef struct {
  lynFrame_t *frame;
  FramePool *pVdecFramePool;  // Frame Pool
  lynBoxesInfo boxInfo;
  BoxInfoEncode *encode;
} RESULT_BOXINFO_T;

// encoding function
std::string to_utf8(wchar_t *wide_string) {
  static std::wstring_convert<std::codecvt_utf8<wchar_t>> utf8_conv;
  return utf8_conv.to_bytes(wide_string);
}

/**
 * @brief 编码 lynBoxesInfo 到 JSON 的实现
 *
 * @param  j
 * @param  info
 */
void to_json(json &j, lynBoxesInfo &info) {
  for (uint32_t i = 0; i < info.boxesNum; ++i) {
    json box = json{
        {"label", info.boxes[i].label}, {"id", info.boxes[i].id},
        {"score", info.boxes[i].score}, {"xmin", info.boxes[i].xmin},
        {"xmax", info.boxes[i].xmax},   {"ymin", info.boxes[i].ymin},
        {"ymax", info.boxes[i].ymax},
    };
    j.emplace_back(box);
  }
}

class BoxInfoEncode {
 private:
  int m_frameNum = 0;
  std::ofstream m_file;
  std::string m_filePath;

 public:
  BoxInfoEncode() {}

  ~BoxInfoEncode() {}

  /**
   * @brief 初始化函数
   *
   * @param  filePath
   * @return true
   * @return false
   */
  bool Init(std::string filePath) {
    m_filePath = filePath;
    m_file.open(filePath);
    m_file << "[" << std::endl;
    return m_file.is_open();
  }

  /**
   * @brief 反初始化函数
   *
   */
  void UnInit() { m_file.close(); }

  /**
   * @brief 编码 lynBoxesInfo 到 JSON 文件
   *
   * @param  info
   * @param  eos
   */
  void EncodeToJson(lynBoxesInfo &info, bool eos) {
    ++m_frameNum;
    uint64_t fileSize = GetFileSize(m_filePath);
    if (fileSize > FILE_MAX_SIZE) {
      std::cout << "only support 500M. " << m_filePath
                << " now file size: " << fileSize << std::endl;
      return;
    }

    // 为避免后续编码大文件导致内存占用过高，现每一帧到达时都进行写入文件操作
    // 外层的数组手动补齐，并区分最后一帧与其他帧
    if (eos) {  // 最后一帧时，补齐 ]
      m_file << std::endl << "]" << std::endl;
    } else {  // 普通帧时，手动添加 ,

      json boxInfos = info;
      json result;
      result["frame"] = m_frameNum;
      result["boxInfos"] = boxInfos;
      result["boxesNum"] = info.boxesNum;
      m_file << std::setw(2) << result;
      m_file << "," << std::endl;
    }
  }
};
